package com.uchiha.nova.mainService.filter;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uchiha.nova.mainService.listener.MyRedisSubscribeListener;
import com.uchiha.nova.mainService.props.AuthProperties;
import com.uchiha.nova.mainService.props.HeaderConstant;
import com.uchiha.nova.mainService.provider.AuthProvider;
import com.uchiha.nova.mainService.provider.GatewayUtil;
import com.uchiha.nova.mainService.provider.RequestProvider;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author 周林静
 * @Date 2022-12-31,0031 21:34
 * @Version 1.0
 */
@Slf4j
@Component
public class BaseFilterGatewayFilterFactory extends AbstractGatewayFilterFactory {

    AuthProperties authProperties;
    PasswordEncoder passwordEncoder;

    ObjectMapper objectMapper;

    RedisTemplate<String, Object> redisTemplate;


    @Override
    public GatewayFilter apply(Object config) {

        return (exchange, chain) -> {
            log.info("BaseGatewayFilterFactory");
            ApplicationContext applicationContext = exchange.getApplicationContext();
            ServerHttpResponse resp = exchange.getResponse();
            if(applicationContext!=null&&applicationContext.getBean("authProperties")!=null&&authProperties==null) {
                authProperties= (AuthProperties) applicationContext.getBean("authProperties");
            }
            if (applicationContext != null && applicationContext.getBean("passwordEncoder") != null && passwordEncoder == null) {
                passwordEncoder = (PasswordEncoder) applicationContext.getBean("passwordEncoder");
            }
            if (applicationContext != null && applicationContext.getBean("redisTemplate") != null && redisTemplate == null) {
                redisTemplate = (RedisTemplate<String, Object>) applicationContext.getBean("redisTemplate");
            }
            if (applicationContext != null && applicationContext.getBean("objectMapper") != null && objectMapper == null) {
                objectMapper = (ObjectMapper) applicationContext.getBean("objectMapper");
            }

            String originalRequestUrl = RequestProvider.getOriginalRequestUrl(exchange);
            log.info("originalRequestUrl-final:{}",originalRequestUrl);
            //从请求头获取basic
            if(originalRequestUrl.contains("?")){
                String unUse = originalRequestUrl.substring(originalRequestUrl.indexOf("?"));
                originalRequestUrl = originalRequestUrl.replace(unUse,"");
            }
            if (GatewayUtil.isSkip(originalRequestUrl,authProperties)) {
                return chain.filter(exchange);
            }
            String Basesic = exchange.getRequest().getHeaders().getFirst(AuthProvider.AUTHORIZATION);
            String Authorization = StrUtil.subAfter(Basesic, "Basic ",false);
            log.info("Authorization:{}",Authorization);
            if(ObjectUtil.isEmpty(Authorization)){
                return GatewayUtil.errorClient(resp, "无效的认证信息",objectMapper);
            }
            String json = new String(Base64.decode(Authorization));;
            log.info("json:{}",json);
            //解码之后拿到client信息
            String clientId = json.substring(0, json.indexOf(":"));
            String clientSecrt = json.substring(clientId.length() + 1);
            //从redis或者内存读取client信息
            Map<String, String> clients = MyRedisSubscribeListener.getClients();
            //内存为空则从redis中读取
            if (clients.isEmpty()) {
                clients = (Map<String, String>) redisTemplate.opsForValue().get("nova:client");
                MyRedisSubscribeListener.setClients(clients);
            }
            String Secret = clients.get(clientId);

            if ("不存在的client".equals(Secret)) {
                return GatewayUtil.errorClient(resp, "无效的Client",objectMapper);
            }
            if (!passwordEncoder.matches(clientSecrt, Secret)) {
                return GatewayUtil.noClient(resp, "无效的clientSecrt",objectMapper);
            }

            ServerHttpRequest request = exchange.getRequest().mutate()
                    .header(HeaderConstant.NOVA_CLIENT,clientId)
                    .header(HeaderConstant.NOVA_CLIENT_SECRT,clientSecrt)
                    .build();
            exchange = exchange.mutate().request(request).build();
            log.info("BaseFilterGatewayFilterFactory通过");
            return chain.filter(exchange);

        };
    }
}
